package cn.edu.sdjzu.xg23.kcsj01_backend.service.impl;

import cn.edu.sdjzu.xg23.kcsj01_backend.entity.Patent;
import cn.edu.sdjzu.xg23.kcsj01_backend.entity.SupportingMaterial;
import cn.edu.sdjzu.xg23.kcsj01_backend.mapper.SupportingMaterialMapper;
import cn.edu.sdjzu.xg23.kcsj01_backend.service.FileService;
import cn.edu.sdjzu.xg23.kcsj01_backend.service.SupportingMaterialService;
import cn.edu.sdjzu.xg23.kcsj01_backend.utils.SnowflakeIdGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class SupportMaterialServiceImpl implements SupportingMaterialService {

    @Autowired
    private SupportingMaterialMapper supportingMaterialMapper;

    @Autowired
    private SnowflakeIdGenerator idGenerator;

    @Autowired
    private FileService fileService;

    private static final Logger log = LoggerFactory.getLogger(SupportMaterialServiceImpl.class);

    @Override
    public boolean addSupportingMaterials(Long achievementId, List<SupportingMaterial> supportingMaterials) {
        if (achievementId == null || supportingMaterials == null || supportingMaterials.isEmpty()) {
            return false;
        }

        List<SupportingMaterial> materialsToSave = supportingMaterials.stream()
                .map(material -> {
                    if (material.getId() == null) {
                        material.setId(idGenerator.generateId());
                    }
                    return material;
                })
                .collect(Collectors.toList());


        // 批量插入支撑材料
       boolean issuccessed  =  supportingMaterialMapper.addSupportingMaterials(achievementId,materialsToSave);

        // 返回保存后的支撑材料列表
        return issuccessed;
    }


    @Override
    public List<SupportingMaterial> findByAchievementId(Long achievementId) {
        return supportingMaterialMapper.findByAchievementId(achievementId);
    }


    @Override
    @Transactional
    public boolean deleteSupportingMaterials(Long achievementId) {
        try {
            // 1. 查询该成果的所有支撑材料
            List<SupportingMaterial> materials = supportingMaterialMapper.findByAchievementId(achievementId);

            // 2. 提取文件URL并删除物理文件
            if (!materials.isEmpty()) {
                List<String> fileUrls = materials.stream()
                        .map(SupportingMaterial::getFileUrl)
                        .collect(Collectors.toList());

                Map<String, Object> deleteResult = fileService.deleteFiles(fileUrls);
                int failCount = (int) deleteResult.get("failCount");
                if (failCount > 0) {
                    @SuppressWarnings("unchecked")
                    List<String> failedFiles = (List<String>) deleteResult.get("failedFiles");
                    log.error("删除支撑材料文件失败: {}", failedFiles);
                }
            }

            // 3. 无需手动删除数据库记录（依赖级联删除）
            return true;
        } catch (Exception e) {
            log.error("删除支撑材料文件失败，成果ID: {}", achievementId, e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }


    /**
     * 更新成果的支撑材料（对比新旧列表，处理新增、删除和保留的文件）
     */
    @Transactional
    public boolean updateSupportingMaterials(Long achievementId, List<SupportingMaterial> newMaterials) {
        try {
            // 1. 查询现有材料
            List<SupportingMaterial> existingMaterials = findByAchievementId(achievementId);

            // 2. 计算差异（需要删除的、需要新增的）
            Map<String, List<SupportingMaterial>> diffResult = calculateMaterialDiff(existingMaterials, newMaterials);
            List<SupportingMaterial> materialsToDelete = diffResult.get("toDelete");
            List<SupportingMaterial> materialsToAdd = diffResult.get("toAdd");

            // 3. 删除需要移除的材料
            if (!materialsToDelete.isEmpty()) {
                // 删除物理文件
                List<String> fileUrlsToDelete = materialsToDelete.stream()
                        .map(SupportingMaterial::getFileUrl)
                        .collect(Collectors.toList());
                fileService.deleteFiles(fileUrlsToDelete);

                // 删除数据库记录
                deleteSupportingMaterialsByIds(
                        materialsToDelete.stream()
                                .map(SupportingMaterial::getId)
                                .collect(Collectors.toList())
                );
            }

            // 4. 添加新的材料
            if (!materialsToAdd.isEmpty()) {
                // 为新文件设置ID和关联的成果ID
                for (SupportingMaterial material : materialsToAdd) {
                    material.setId(idGenerator.generateId());
                    material.setAchievement(new Patent(achievementId));
                }

                // 批量插入新文件
                return addSupportingMaterials(achievementId, materialsToAdd);
            }

            return true;
        } catch (Exception e) {
            log.error("更新支撑材料失败，成果ID: {}", achievementId, e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
    }

    /**
     * 计算支撑材料差异（现有材料 vs 新材料）
     */
    private Map<String, List<SupportingMaterial>> calculateMaterialDiff(
            List<SupportingMaterial> existingMaterials,
            List<SupportingMaterial> newMaterials) {
        Map<String, List<SupportingMaterial>> result = new HashMap<>();

        // 需要删除的材料（现有但不在新列表中）
        List<SupportingMaterial> toDelete = existingMaterials.stream()
                .filter(existing -> newMaterials.stream()
                        .noneMatch(newMat -> newMat.getFileUrl().equals(existing.getFileUrl())))
                .collect(Collectors.toList());

        // 需要新增的材料（新列表中有但现有列表没有）
        List<SupportingMaterial> toAdd = newMaterials.stream()
                .filter(newMat -> existingMaterials.stream()
                        .noneMatch(existing -> existing.getFileUrl().equals(newMat.getFileUrl())))
                .collect(Collectors.toList());

        result.put("toDelete", toDelete);
        result.put("toAdd", toAdd);
        return result;
    }


    @Override
    public boolean deleteSupportingMaterialsByIds(List<Long> ids) {
        try {
            return supportingMaterialMapper.deleteByIds(ids) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
